package com.anjian.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;

import com.anjian.model.Scope;
import com.anjian.taobao.TaobaoProxy;
import com.anjian.utils.PagingResult;
import com.opensymphony.xwork2.ActionContext;
import com.taobao.api.ApiException;
import com.taobao.api.domain.Item;
import com.taobao.api.response.ItemUpdateResponse;
import com.taobao.api.response.ItemsInventoryGetResponse;
import com.taobao.api.response.ItemsOnsaleGetResponse;

public class DetectAction extends ActionBase {

	static Logger _log = Logger.getLogger(DetectAction.class.getName());

	private static final String TOTAL = "total";
	
	private Scope scope;
	private List<ItemUpdateResponse> errorItems;
	private Map<String, Object> session;
	private long spend;
	
	public String execute() throws Exception {
		session = ActionContext.getContext().getSession();
		session.remove(DONE);
		new Thread()
		{
			public void run()
			{
				try {
					detect();
				} catch (Exception e) {
					error(e);
				}
			}
		}.start();
		_log.info("thread starteddddddddddddddddddddddd");
		return SUCCESS;
	}
	
	private String detect() throws Exception {
		long t0 = System.currentTimeMillis();
		errorItems = new ArrayList<ItemUpdateResponse>();
		String sessionId = (String)session.get(TOP_SESSION);
		_log.info("scope: " + scope);
		if (!StringUtils.isEmpty(scope.getSaleStatus()) && scope.getSaleStatus().contains("onsale"))
		{
			resetProgress();
			session.put(STATUS, ONSALE);
			long total = detectSales(1, sessionId, session);
			int pages = PagingResult.getPageCount(total, PAGE_SIZE);
			_log.info(getUser() + " - pages: " + pages + ", total: " + total);
			if (total != -1)
			{
				for (int i = 2; i <= pages; i++)
				{
					if (errorItems.size() >= MAX_ERROR)
					{
						break;
					}
					_log.info(getUser() + "...scanning onsales on page " + i);
					detectSales(i, sessionId, session);
				}
			}
		}
		if (!StringUtils.isEmpty(scope.getSaleStatus()) && scope.getSaleStatus().contains("inventory"))
		{
			resetProgress();
			session.put(STATUS, INVENTORY);
			long total = detectInventory(1, sessionId, session);
			int pages = PagingResult.getPageCount(total, PAGE_SIZE);
			_log.info(getUser() + " - pages: " + pages + ", total: " + total);
			if (total != -1)
			{
				for (int i = 2; i <= pages; i++)
				{
					if (errorItems.size() >= MAX_ERROR)
					{
						break;
					}
					_log.info(getUser() + "...scanning inventory on page " + i);
					detectInventory(i, sessionId, session);
				}
			}
		}
		spend = (System.currentTimeMillis() - t0) / 1000;
		if (errorItems != null)
		{
			_log.info("complete scanning and found error items: " + errorItems.size());
		}
		session.put(ERROR_ITEMS, errorItems);
		session.put(TIME_SPENT, spend);
		session.put(LAST_SCAN, new Date());
		session.put(DONE, true);
		return SUCCESS;
	}
	
	private long detectSales(int pageNo, String sessionId, Map<String, Object> session) throws Exception
	{
		ItemsOnsaleGetResponse onsales = TaobaoProxy.getOnSales(sessionId, pageNo, PAGE_SIZE, scope.getSellerCids(), null);
		if (onsales.isSuccess())
		{
			long total = onsales.getTotalResults();
			_log.info("onsale.total: " + total);
			session.put(TOTAL, total);
			List<Item> items = onsales.getItems();
			if (items != null)
			{
				detectItems(items, sessionId);
			}
			return total;
		}
		else
		{
			error(onsales);
//			if ("accesscontrol.limited-by-app-access-count".equals(onsales.getSubCode()))
//			{
//				throw new Exception("out-of-band");
//			}
		}
		return -1L;
	}
	
	private long detectInventory(int pageNo, String sessionId, Map<String, Object> session) throws Exception
	{
		ItemsInventoryGetResponse inventory = TaobaoProxy.getInventory(sessionId, pageNo, PAGE_SIZE, null, scope.getSellerCids(), null);
		if (inventory.isSuccess())
		{
			long total = inventory.getTotalResults();
			_log.info("inventory.total: " + total);
			session.put(TOTAL, total);
			List<Item> items = inventory.getItems();
			if (items != null)
			{
				detectItems(items, sessionId);
			}
			return total;
		}
		else
		{
			error(inventory);
//			if ("accesscontrol.limited-by-app-access-count".equals(inventory.getSubCode()))
//			{
//				throw new Exception("out-of-band");
//			}
		}
		return -1L;
	}
	
	private void detectItems(List<Item> items, String sessionId)
	{
		Map<Long,Long> notRepeatCids = new HashMap<Long,Long>();
		for (Item item : items)
		{
			_log.info("checking: " + item.getNumIid());
			if (!notRepeatCids.containsKey(item.getCid()))
			{
				_log.info("11111");
				try {
					ItemUpdateResponse rsp = TaobaoProxy.updateItem(sessionId, item.getNumIid());
					_log.info("22222");
					if (!rsp.isSuccess())
					{
						_log.info("code: " + rsp.getErrorCode() + " msg: " + rsp.getMsg() + " subCode: " + rsp.getSubCode() + " subMsg: " + rsp.getSubMsg());
						String subCode = rsp.getSubCode();
						if (isRepeatError(subCode))
						{
							_log.info("ignore cid: " + item.getCid());
							notRepeatCids.put(item.getCid(), item.getCid());
						}
						if (subCode != null && !isSystemError(subCode))
						{
							rsp.setItem(item); 
							errorItems.add(rsp);
						}
						if (errorItems.size() >= MAX_ERROR)
						{
							return;
						}
					}
				} catch (ApiException e) {
					_log.log(Level.SEVERE, "", e);
				}
				catch (Exception e) {
					_log.log(Level.SEVERE, "", e);
				}
			}
			increaceProgress();
		}
	}
	
	public List<ItemUpdateResponse> getErrorItems()
	{
		if (errorItems != null)
		{
			_log.info("size: " + errorItems.size());
		}
		return errorItems;
	}
	
	public long getSpend()
	{
		return spend;
	}
	
	protected void resetProgress()
	{
		_log.info("sssssssssss: " + session);
		session.put(PROGRESS, 0);
	}
	
	protected void increaceProgress()
	{
		Integer progress = (Integer)session.get(PROGRESS);
		_log.info(getUser() + "progress: " + progress);
		if (progress == null)
		{
			progress = 0;
		}
		session.put(PROGRESS, ++progress);
	}
	
	protected String getUser()
	{
		return (String)session.get(USER);
	}
	
	public Scope getScope() {
		return scope;
	}

	public void setScope(Scope scope) {
		this.scope = scope;
	}
}
